package api

import (
	"fmt"
	"gitee.com/tang_q/gin-vue3-admin-api/global"
	"gitee.com/tang_q/gin-vue3-admin-api/model"
	"gitee.com/tang_q/gin-vue3-admin-api/model/dto"
	"gitee.com/tang_q/gin-vue3-admin-api/utils"
	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
	"github.com/spf13/viper"
	"os"
	"path/filepath"
	"time"
)

type UserApi struct {
	BaseApi
}

func NewUserApi() UserApi {
	return UserApi{
		NewBaseApi(),
	}
}

// Login 登录
//
//	@Summary		登录
//	@Schemes		http
//	@Tags			登录
//	@Description	登录
//	@Accept			json
//	@Produce		json
//	@Param			name		query	string	true	"用户名"
//	@param			password	query	string	true	"密码"
//	@Success		200			{json}	{"code":0,"msg":"成功"}
//	@Router			/aip/public/user/login [post]
func (a UserApi) Login(c *gin.Context) {
	a.ctx = c
	userLoginDto := dto.UserLoginDTO{}
	err := c.ShouldBind(&userLoginDto)
	if err != nil {
		a.Fail(201, "参数错误"+fmt.Sprintf("%v", err), nil)
		return
	}
	users := model.Users{}
	if err := users.GetUsersByLoginName(userLoginDto.LoginName); err != nil {
		global.Logger.Error(err)
		a.Fail(201, "账号不存在", nil)
		return
	}
	if userLoginDto.UserPassword != users.Password {
		global.Logger.Error("账号或密码错误")
		a.Fail(201, "账号或密码错误", nil)
		return
	}
	if users.Status == 0 {
		a.Fail(201, "账号已被禁用", nil)
		return
	}
	roleIds, err := users.GetRoleIdsByUserId(users.ID)
	if err != nil {
		global.Logger.Error(err)
		a.Fail(201, "获取用户角色失败"+fmt.Sprintf("%v", err), nil)
		return
	}
	t := map[string]any{}
	token, err := utils.MyCustomClaims(userLoginDto.LoginName, users.ID, roleIds)
	if err != nil {
		global.Logger.Error(err)
		a.Fail(201, "生成token失败"+fmt.Sprintf("%v", err), nil)
		return
	}
	// 更新登录时间
	_ = model.UpdateLoginTime(users.ID)

	t["token"] = token
	a.Success("登录成功", t)
}

// GetUsersInfo 通过登录名获取用户信息及其菜单和按钮
//
//	@Summary		通过登录名获取用户信息及其菜单和按钮
//	@Description	根据传入的登录名，获取对应的用户信息、该用户可访问的菜单和按钮
//	@Tags			用户接口
//	@Accept			json
//	@Produce		json
//	@Param			loginName	query	string	true	"登录名"
//	@Success		200			{json}	{"code":200,"msg":"成功",data:{"userInfo":any,"routes":any,"buttons":any}}
//	@Failure		201			{json}	{"code":201,"msg":"获取用户信息失败","data":nil}
//	@Router			/api/v1/public/users/info [get]
func (a UserApi) GetUsersInfo(context *gin.Context) {
	a.ctx = context
	loginName, _ := context.Get("loginName")
	users := model.Users{}
	err := users.GetUsersByLoginName(loginName.(string))
	if err != nil {
		global.Logger.Error(err)
		a.Fail(201, "获取用户信息失败"+fmt.Sprintf("%v", err), nil)
		return
	}
	userIfno := dto.UserLoginInfoDTO{
		UserName:  users.UserName,
		LoginName: users.LoginName,
		Avatar:    users.Avatar,
		ID:        users.ID,
	}
	userData := map[string]any{}
	userData["userInfo"] = userIfno
	userData["routes"], err = users.GetMenusRouterThereByLoginName(users.LoginName)
	if err != nil {
		global.Logger.Error(err)
		a.Fail(201, "获取用户菜单失败"+fmt.Sprintf("%v", err), nil)
		return
	}
	userData["buttons"], err = users.GetButtonsByLoginName(users.LoginName)
	if err != nil {
		global.Logger.Error(err)
		a.Fail(201, "获取用户按钮失败"+fmt.Sprintf("%v", err), nil)
		return
	}
	a.Success("获取用户信息成功", userData)
}

// CreateUser 创建新用户
//
//	@Summary		创建新用户
//	@Description	根据请求体中的用户信息，创建一个新用户，并返回操作结果
//	@Tags			用户接口
//	@Accept			json
//	@Produce		json
//	@Param			loginName	header		string				true	"当前登录用户的登录名"
//	@Param			addUserDto	body		dto.UserRegisterDTO	true	"用户注册信息"
//	@Success		200			{object}	api.ResponseJson	"添加用户成功"
//	@Failure		201			{object}	api.ResponseJson	"参数错误或添加用户失败"
//	@Router			/api/v1/user/createUser [post]
func (a UserApi) CreateUser(c *gin.Context) {
	a.ctx = c
	addUserDto := dto.UserRegisterDTO{}
	loginName, _ := c.Get("loginName")
	thisLoginUser := model.Users{}
	_ = thisLoginUser.GetUsersByLoginName(loginName.(string))

	err := c.ShouldBind(&addUserDto)
	if err != nil {
		a.Fail(201, "参数错误"+fmt.Sprintf("%v", err), nil)
		return
	}
	user := model.Users{}
	user.CreatedUser = &thisLoginUser
	user.UpdatedUser = &thisLoginUser
	err = user.Create(addUserDto)
	if err != nil {
		global.Logger.Error(err)
		a.Fail(201, "添加用户失败"+fmt.Sprintf("%v", err), nil)
		return
	}
	a.Success("添加用户成功", nil)
}

// Logout 用户退出登录
func (a UserApi) Logout(c *gin.Context) {
	a.ctx = c
	token := a.ctx.GetHeader("Authorization")
	cl, _ := utils.ParseTokenHs256(token)
	tokenID := cl.ID
	global.Redis.Set(c, tokenID, "", time.Minute*viper.GetDuration("jwt.tokenExpire"))

	a.Success("退出登录成功", nil)
}

func (u UserApi) GetUsersList(c *gin.Context) {
	u.ctx = c
	userQueryDto := dto.UserQueryDTO{}
	if err := c.ShouldBind(&userQueryDto); err != nil {
		global.Logger.Error(err)
		u.Fail(201, "参数错误"+fmt.Sprintf("%v", err), nil)
		return
	}
	userList, total, err := model.GetUserList(userQueryDto)
	if err != nil {
		global.Logger.Error(err)
		u.Fail(201, "获取用户列表失败"+fmt.Sprintf("%v", err), nil)
		return
	}
	roleList, err := model.GetRoles()
	if err != nil {
		global.Logger.Error(err)
		u.Fail(201, "获取角色列表失败"+fmt.Sprintf("%v", err), nil)
		return
	}
	u.Success("获取用户列表成功", gin.H{
		"userList": userList,
		"total":    total,
		"roleList": roleList,
	})
}

// UpdateUser 更新用户
func (u UserApi) UpdateUser(c *gin.Context) {
	u.ctx = c
	updateUserDto := dto.UpdateUserDTO{}
	loginName, _ := c.Get("loginName")
	err := c.ShouldBind(&updateUserDto)
	if err != nil {
		global.Logger.Error(err)
		u.Fail(201, "参数错误"+fmt.Sprintf("%v", err), nil)
		return
	}
	thisLoginUser := model.Users{}
	_ = thisLoginUser.GetUsersByLoginName(loginName.(string))
	user := model.Users{}
	err = user.Update(updateUserDto, &thisLoginUser)
	if err != nil {
		global.Logger.Error(err)
		u.Fail(201, "更新用户失败"+fmt.Sprintf("%v", err), nil)
		return
	}
	u.Success("更新用户成功", nil)
}

// UploadAvatar 上传头像
func (u UserApi) UploadAvatar(c *gin.Context) {
	u.ctx = c
	file, err := c.FormFile("avatar")
	if err != nil {
		global.Logger.Error(err)
		u.Fail(201, "上传头像失败"+fmt.Sprintf("%v", err), nil)
		return
	}
	uploadPath := "./uploads/avatar/"
	err = os.MkdirAll(uploadPath, os.ModePerm)
	if err != nil {
		global.Logger.Error(err)
		u.Fail(201, "上传头像失败"+fmt.Sprintf("%v", err), nil)
		return
	}
	// 使用 UUID 生成唯一文件名，保留原始扩展名
	ext := filepath.Ext(file.Filename)
	fileName := uuid.New().String() + ext
	filePath := filepath.Join(uploadPath, fileName)
	// 保存文件
	if err := c.SaveUploadedFile(file, filePath); err != nil {
		u.Fail(201, "上传头像失败"+fmt.Sprintf("%v", err), nil)
		return
	}

	// 返回文件路径
	u.Success("上传头像成功", gin.H{
		"avatar": fileName,
	})
}
func (u UserApi) GetUserAvatar(c *gin.Context) {
	u.ctx = c
	filename := c.Param("filename")
	fmt.Println("filename:", filename)
	// 拼接图片路径
	filePath := filepath.Join("./uploads/avatar/", filename)

	// 检查文件是否存在
	if _, err := os.Stat(filePath); os.IsNotExist(err) {
		u.Fail(404, "文件不存在", nil)
		return
	}

	// 设置 Content-Type 以确保图片能够正确显示
	// 把文件
	c.File(filePath)
}

// UpdateAvatar 更新用户头像
func (u UserApi) UpdateAvatar(c *gin.Context) {
	u.ctx = c
	avatar := c.Param("filename")
	loginName, _ := c.Get("loginName")
	user := model.Users{}
	err := user.GetUsersByLoginName(loginName.(string))
	if err != nil {
		global.Logger.Error(err)
		u.Fail(201, "更新用户头像失败"+fmt.Sprintf("%v", err), nil)
		return
	}
	err = user.UpdateAvatar(avatar)
	if err != nil {
		global.Logger.Error(err)
		u.Fail(201, "更新用户头像失败"+fmt.Sprintf("%v", err), nil)
		return
	}
	u.Success("更新用户头像成功", nil)
}

// DeleteUser 删除用户
func (u UserApi) DeleteUser(c *gin.Context) {
	u.ctx = c
	id := c.Query("id")
	err := model.DeleteUser(id)
	if err != nil {
		global.Logger.Error(err)
		u.Fail(201, "删除用户失败"+fmt.Sprintf("%v", err), nil)
		return
	}
	u.Success("删除用户成功", nil)
}

// DeleteUsers 批量删除用户
func (u UserApi) DeleteUsers(c *gin.Context) {
	u.ctx = c
	ids := dto.DelUserByIDsReq{}
	if err := c.ShouldBind(&ids); err != nil {
		global.Logger.Error(err)
		u.Fail(201, "参数错误"+fmt.Sprintf("%v", err), nil)
		return
	}
	err := model.DeleteUsers(ids)
	if err != nil {
		global.Logger.Error(err)
		u.Fail(201, "删除用户失败"+fmt.Sprintf("%v", err), nil)
		return
	}
	u.Success("删除用户成功", nil)
}

func (u UserApi) GetUserPInfo(c *gin.Context) {
	u.ctx = c
	loginName, _ := c.Get("loginName")
	user := model.Users{}
	err := user.GetUsersByLoginName(loginName.(string))
	if err != nil {
		global.Logger.Error(err)
		u.Fail(201, "获取用户信息失败"+fmt.Sprintf("%v", err), nil)
		return
	}
	u.Success("获取用户信息成功", gin.H{
		"userInfo": user,
	})
}

func (u UserApi) UpdateInfo(c *gin.Context) {
	u.ctx = c
	data := dto.UpdateUserInfoDTO{}
	if err := c.ShouldBind(&data); err != nil {
		global.Logger.Error(err)
		u.Fail(201, "参数错误"+fmt.Sprintf("%v", err), nil)
		return
	}
	user := model.Users{}
	err := user.UpdateUserInfo(data)
	if err != nil {
		global.Logger.Error(err)
		u.Fail(201, "更新用户信息失败"+fmt.Sprintf("%v", err), nil)
		return
	}
	u.Success("更新用户信息成功", nil)
}
